package com.cssl.gulimall.product.web;

import com.cssl.common.entity.product.CategoryEntity;
import com.cssl.common.vo.product.Catalog2VO;
import com.cssl.gulimall.product.service.CategoryService;
import org.redisson.api.RCountDownLatch;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Controller
public class IndexController {
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @GetMapping({"/index","/"})
    public String index(Model model){
        List<CategoryEntity> categoryEntitys  = categoryService.getLevel1Categorys();
        model.addAttribute("categorys",categoryEntitys);
        return "index";
    }

    /**
     * 查询三级分类
     * {
     *     "一级分类ID": [
     *         {
     *             "catalog1Id": "一级分类ID",
     *             "id": "二级分类ID",
     *             "name": "二级分类名",
     *             "catalog3List":[
     *                 {
     *                     "catalog2Id": "二级分类ID",
     *                     "id": "三级分类ID",
     *                     "name": "三级分类名"
     *                 }
     *             ]
     *         }
     *     ],
     *     "一级分类ID": [],
     *     "一级分类ID": []
     * }
     */
    @ResponseBody
    @GetMapping("/index/catalog.json")
    public Map<String, List<Catalog2VO>> getCatalogJson() {
        Map<String, List<Catalog2VO>> map = categoryService.getCatalogJsonWithSpringCache();
        return map;
    }

    @ResponseBody
    @GetMapping("/hello")
    public String hello(){
        RLock lock = redissonClient.getLock("my-lock");
        /*
            lock.lock();
           不指定过期时间时，每过10s，锁自动续期+30S(看门狗)
           如果线程宕机，看门狗不会自动续期，锁会自动过期
         */
        lock.lock();
//        lock.lock(10, TimeUnit.SECONDS);
        try {
            System.out.println("加锁成功,执行业务....."+Thread.currentThread().getId());
            Thread.sleep(5000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("释放锁..."+Thread.currentThread().getId());
            lock.unlock();
        }
        return  "hello";
    }

    /*
    测试读写锁 读和写用的同意吧锁，并发下读操作互不影响
    如果写锁被占用了，读锁要等写锁释放后才能读
    读锁-共享锁  写锁-互斥锁
     */
    @ResponseBody
    @GetMapping("/write")
    public String write(){
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("rw-lock");
        RLock rLock = readWriteLock.writeLock();
        try {
            rLock.lock();
            Thread.sleep(15000);
            String s = UUID.randomUUID().toString();
            redisTemplate.opsForValue().set("writeValue",s);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rLock.unlock();
        }
        return "写数据";
    }

    @ResponseBody
    @GetMapping("/read")
    public String read(){
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("rw-lock");
        RLock rLock = readWriteLock.readLock();
        String readValue = "";
        try {
            rLock.lock();
            readValue = redisTemplate.opsForValue().get("writeValue");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rLock.unlock();
        }
        return readValue;
    }

    /*
    测试闭锁
     */
    @ResponseBody
    @GetMapping("/lockDoor")
    public String lockDoor() throws InterruptedException {
        RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("door");
        countDownLatch.trySetCount(5);
        countDownLatch.await();
        return "放假了..";
    }

    @ResponseBody
    @GetMapping("/gogogo/{id}")
    public String gogogo(@PathVariable("id") Integer id) throws InterruptedException {
        RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("door");
        countDownLatch.countDown();
        return id+"班走了..";
    }
}
